﻿// Copyright © Microsoft Corporation.  All Rights Reserved.
// This code released under the terms of the 
// Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.ServiceModel.Syndication;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xml;

namespace TheOliver.Controls
{
    public class FeedReader : UserControl, INotifyPropertyChanged
    {
        public FeedReader()
        {
            if (DesignerProperties.GetIsInDesignMode(this))
            {
                StackPanel sp = new StackPanel();
                sp.Background = new SolidColorBrush(Colors.Red);

                TextBlock tb = new TextBlock();
                tb.Text = "[Feed Reader Service]";

                sp.Children.Add(tb);
                this.Content = sp;
                return;
            }
        }

        public string FeedUrl
        {
            get { return (string)GetValue(FeedUrlProperty); }
            set { SetValue(FeedUrlProperty, value); }
        }

        // Using a DependencyProperty as the backing store for FeedUrl.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty FeedUrlProperty =
            DependencyProperty.Register(
                "FeedUrl",
                typeof(string),
                typeof(FeedReader),
                new PropertyMetadata("http://blogs.msdn.com/olivers/rss.xml", OnFeedUrlChanged));

        private static void OnFeedUrlChanged(DependencyObject senedr, DependencyPropertyChangedEventArgs args)
        {
        }

        private bool _isBusy = false;
        public bool IsBusy
        {
            get { return _isBusy; }
            set
            {
                _isBusy = value;
                OnPropertyChanged("IsBusy");
                this.IsIdle = !_isBusy;
            }
        }

        private bool _isIdle = true;
        public bool IsIdle
        {
            get { return _isIdle; }
            set
            {
                _isIdle = value;
                OnPropertyChanged("IsIdle");
            }
        }

        private SyndicationFeed _feed;
        public SyndicationFeed Feed
        {
            get { return _feed; }
            set 
            { 
                _feed = value; 
                OnPropertyChanged("Feed"); 
                this.Items = _feed.Items;
                this.Categories = _feed.Categories;
            }
        }

        private IEnumerable<SyndicationCategory> _categories;
        public IEnumerable<SyndicationCategory> Categories
        {
            get { return _categories; }
            set 
            {
                _categories = value;
                OnPropertyChanged("Categories"); 
                _categories = value; 
            }
        }

        private IEnumerable<SyndicationItem> _items;
        public IEnumerable<SyndicationItem> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged("Items"); }
        }

        public bool AutoLoad
        {
            get { return (bool)GetValue(AutoLoadProperty); }
            set { SetValue(AutoLoadProperty, value); }
        }

        public static readonly DependencyProperty AutoLoadProperty =
            DependencyProperty.Register(
                "AutoLoad",
                typeof(bool),
                typeof(FeedReader),
                new PropertyMetadata(true));

        public void Load()
        {
            if (FeedUrl == null || FeedUrl.Length <= 0)
            {
                RaiseError(new Exception("No Feed Url defined"));
                return;
            }

            this.IsBusy = true;

            Uri twitterUri = new Uri(FeedUrl);

            WebClient webClient = new WebClient();
            webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
            webClient.DownloadStringAsync(twitterUri);
        }

        void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                RaiseError(e.Error);
                return;
            }

            StringReader sr = new StringReader(e.Result);
            XmlReader xr = XmlReader.Create(sr);
            SyndicationFeed feed = SyndicationFeed.Load(xr);

            OnFeedLoaded(feed);
        }

        public void Load(string feedUrl)
        {
            this.FeedUrl = feedUrl;
            Load();
        }

        public event NewsFeedLoadedEventHandler FeedLoaded;
        public event NewsFeedErrorEventHandler FeedError;

        private void OnFeedLoaded(SyndicationFeed feed)
        {
            this.IsBusy = false;
            if (FeedLoaded != null)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    NewsFeedLoadedEventArgs args = new NewsFeedLoadedEventArgs();
                    args.Feed = feed;
                    FeedLoaded(this, args);
                });
            }
            this.Feed = feed;
        }

        private void RaiseError(Exception exc)
        {
            this.IsBusy = false;
            if (FeedError != null)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    NewsFeedErrorEventArgs args = new NewsFeedErrorEventArgs();
                    args.Error = exc;
                    FeedError(this, args);
                });
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                Dispatcher.BeginInvoke(() =>
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                });
            }
        }
    }

    public delegate void NewsFeedLoadedEventHandler(object sender, NewsFeedLoadedEventArgs args);

    public class NewsFeedLoadedEventArgs : EventArgs
    {
        public SyndicationFeed Feed { get; set; }
    }

    public delegate void NewsFeedErrorEventHandler(object sender, NewsFeedErrorEventArgs args);

    public class NewsFeedErrorEventArgs
    {
        public Exception Error { get; set; }
    }

}
